Getting Started
Install paste python package
You can install the package on pypi: https://pypi.org/project/paste-bio/
[1]:
import time
import pandas as pd
import numpy as np
import scanpy as sc
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from paste3.visualization import plot_slice, stack_slices_pairwise, stack_slices_center
from paste3.paste import pairwise_align, center_align
from paste3.helper import filter_for_common_genes, match_spots_using_spatial_heuristic
Read data and create AnnData object
[2]:
data_dir = "../../../tests/data/input/"
# Assume that the coordinates of slices are named slice_name + "_coor.csv"
def load_slices(data_dir, slice_names=["slice1", "slice2", "slice3", "slice4"]):
slices = []
for slice_name in slice_names:
slice_i = sc.read_csv(data_dir + slice_name + ".csv")
slice_i_coor = np.genfromtxt(data_dir + slice_name + "_coor.csv", delimiter=",")
slice_i.obsm["spatial"] = slice_i_coor
# Preprocess slices
sc.pp.filter_genes(slice_i, min_counts=15)
sc.pp.filter_cells(slice_i, min_counts=100)
slices.append(slice_i)
return slices
slices = load_slices(data_dir)
slice1, slice2, slice3, slice4 = slices
Each AnnData object consists of a gene expression matrx and spatial coordinate matrix.
[3]:
slice1.X
[3]:
array([[12., 0., 6., ..., 0., 0., 0.],
[ 7., 0., 1., ..., 1., 0., 0.],
[15., 1., 4., ..., 0., 0., 1.],
...,
[ 0., 0., 0., ..., 0., 0., 0.],
[ 1., 0., 0., ..., 0., 0., 0.],
[ 5., 0., 1., ..., 1., 0., 0.]], dtype=float32)
[4]:
slice1.obsm["spatial"][0:5, :]
[4]:
array([[13.064, 6.086],
[12.116, 7.015],
[13.945, 6.999],
[12.987, 7.011],
[15.011, 7.984]])
Note, you can choose to label the spots however you want. In this case, we use the default coordinates.
[5]:
slice1.obs
[5]:
| n_counts | |
|---|---|
| 13.064x6.086 | 2181.0 |
| 12.116x7.015 | 2295.0 |
| 13.945x6.999 | 3375.0 |
| 12.987x7.011 | 2935.0 |
| 15.011x7.984 | 2964.0 |
| ... | ... |
| 21.953x24.847 | 541.0 |
| 20.98x24.963 | 860.0 |
| 20.063x24.964 | 508.0 |
| 19.007x25.045 | 626.0 |
| 21.957x25.871 | 2515.0 |
254 rows × 1 columns
[6]:
slice1.var
[6]:
| n_counts | |
|---|---|
| GAPDH | 2233.0 |
| UBE2G2 | 78.0 |
| MAPKAPK2 | 255.0 |
| NDUFA7 | 96.0 |
| ASNA1 | 172.0 |
| ... | ... |
| DIP2C | 31.0 |
| LYPLA2 | 19.0 |
| RGP1 | 24.0 |
| BPGM | 17.0 |
| HPS6 | 16.0 |
7998 rows × 1 columns
We can visualize the spatial coordinates of our slices using plot_slices.
[7]:
slice_colors = ["#e41a1c", "#377eb8", "#4daf4a", "#984ea3"]
fig, axs = plt.subplots(2, 2, figsize=(7, 7))
plot_slice(slice1, slice_colors[0], ax=axs[0, 0])
plot_slice(slice2, slice_colors[1], ax=axs[0, 1])
plot_slice(slice3, slice_colors[2], ax=axs[1, 0])
plot_slice(slice4, slice_colors[3], ax=axs[1, 1])
plt.show()
We can also plot using Scanpy’s spatial plotting function.
[8]:
sc.pl.spatial(slice1, color="n_counts", spot_size=1)
Pairwise Alignment
Run PASTE pairwise_align.
[9]:
start = time.time()
pi12 = pairwise_align(slice1, slice2)
pi23 = pairwise_align(slice2, slice3)
pi34 = pairwise_align(slice3, slice4)
print("Runtime: " + str(time.time() - start))
Using selected backend cpu. If you want to use gpu, set use_gpu = True.
Using selected backend cpu. If you want to use gpu, set use_gpu = True.
Using selected backend cpu. If you want to use gpu, set use_gpu = True.
Runtime: 0.4654731750488281
[10]:
pd.DataFrame(pi12)
[10]:
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ... | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0.003937 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.000000e+00 | 0.000000 | 0.000000 |
| 1 | 0.000063 | 0.003874 | 0.000000 | 0.0 | 0.0 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.000000e+00 | 0.000000 | 0.000000 |
| 2 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.003937 | 0.000000 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.000000e+00 | 0.000000 | 0.000000 |
| 3 | 0.000000 | 0.000126 | 0.003811 | 0.0 | 0.0 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.000000e+00 | 0.000000 | 0.000000 |
| 4 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.000000 | 0.003874 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.000000e+00 | 0.000000 | 0.000000 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 249 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | 3.937008e-03 | 0.000000 | 0.000000 |
| 250 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | 6.299213e-05 | 0.003874 | 0.000000 |
| 251 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.000000 | 0.000126 | 0.003811 | 0.0 | 0.0 | 0.0 | 9.107298e-17 | 0.000000 | 0.000000 |
| 252 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.003748 | 0.000000 | 0.000189 | 0.0 | 0.0 | 0.0 | 0.000000e+00 | 0.000000 | 0.000000 |
| 253 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.000000e+00 | 0.000000 | 0.003937 |
254 rows × 250 columns
Sequential pairwise slice alignment plots
[11]:
pis = [pi12, pi23, pi34]
slices = [slice1, slice2, slice3, slice4]
new_slices = stack_slices_pairwise(slices, pis)
Now that we’ve aligned the spatial coordinates, we can plot them all on the same coordinate system.
[12]:
slice_colors = ["#e41a1c", "#377eb8", "#4daf4a", "#984ea3"]
plt.figure(figsize=(7, 7))
for i in range(len(new_slices)):
plot_slice(new_slices[i], slice_colors[i], s=400)
plt.legend(
handles=[
mpatches.Patch(color=slice_colors[0], label="1"),
mpatches.Patch(color=slice_colors[1], label="2"),
mpatches.Patch(color=slice_colors[2], label="3"),
mpatches.Patch(color=slice_colors[3], label="4"),
]
)
plt.gca().invert_yaxis()
plt.axis("off")
plt.show()
We can also plot pairwise layers together.
[13]:
slice_colors = ["#e41a1c", "#377eb8", "#4daf4a", "#984ea3"]
fig, axs = plt.subplots(2, 2, figsize=(7, 7))
plot_slice(new_slices[0], slice_colors[0], ax=axs[0, 0])
plot_slice(new_slices[1], slice_colors[1], ax=axs[0, 0])
plot_slice(new_slices[1], slice_colors[1], ax=axs[0, 1])
plot_slice(new_slices[2], slice_colors[2], ax=axs[0, 1])
plot_slice(new_slices[2], slice_colors[2], ax=axs[1, 0])
plot_slice(new_slices[3], slice_colors[3], ax=axs[1, 0])
fig.delaxes(axs[1, 1])
plt.show()
We can also plot the slices in 3-D.
[14]:
import plotly.express as px
import plotly.io as pio
pio.renderers.default = "notebook"
slices_colors = ["#e41a1c", "#377eb8", "#4daf4a", "#984ea3"]
# scale the distance between layers
z_scale = 2
values = []
for i, L in enumerate(new_slices):
for x, y in L.obsm["spatial"]:
values.append([x, y, i * z_scale, str(i)])
df = pd.DataFrame(values, columns=["x", "y", "z", "slice"])
fig = px.scatter_3d(
df, x="x", y="y", z="z", color="slice", color_discrete_sequence=slice_colors
)
fig.update_layout(scene_aspectmode="data")
fig.show()
Center Alignment
First, we will read in and preprocess the data (if you ran pairwise_align above, it will be altered).
[15]:
slices = load_slices(data_dir)
slice1, slice2, slice3, slice4 = slices
Run PASTE center_align.
[16]:
slices = [slice1, slice2, slice3, slice4]
initial_slice = slice1.copy()
lmbda = len(slices) * [1 / len(slices)]
Now, for center alignment, we can provide initial mappings between the center and original slices to PASTE to improve the algorithm. However, note this is optional.
[17]:
filter_for_common_genes(slices)
b = []
for i in range(len(slices)):
b.append(match_spots_using_spatial_heuristic(slices[0].X, slices[i].X))
Filtered all slices for common genes. There are 6397 common genes.
[18]:
start = time.time()
center_slice, pis = center_align(
initial_slice, slices, lmbda, random_seed=5, pis_init=b
)
print("Runtime: " + str(time.time() - start))
Using selected backend cpu. If you want to use gpu, set use_gpu = True.
Filtered all slices for common genes. There are 6397 common genes.
/opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/site-packages/sklearn/decomposition/_nmf.py:1759: ConvergenceWarning:
Maximum number of iterations 200 reached. Increase it to improve convergence.
Iteration: 0
Solving Pairwise Slice Alignment Problem.
Solving Center Mapping NMF Problem.
/opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/site-packages/sklearn/decomposition/_nmf.py:1759: ConvergenceWarning:
Maximum number of iterations 200 reached. Increase it to improve convergence.
Objective -13.865895857292184
Difference: 13.865895857292184
Iteration: 1
Solving Pairwise Slice Alignment Problem.
Solving Center Mapping NMF Problem.
/opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/site-packages/sklearn/decomposition/_nmf.py:1759: ConvergenceWarning:
Maximum number of iterations 200 reached. Increase it to improve convergence.
Objective 1.3829700024632259
Difference: 15.24886585975541
Iteration: 2
Solving Pairwise Slice Alignment Problem.
Solving Center Mapping NMF Problem.
/opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/site-packages/sklearn/decomposition/_nmf.py:1759: ConvergenceWarning:
Maximum number of iterations 200 reached. Increase it to improve convergence.
Objective 1.3881010157761822
Difference: 0.00513101331295629
Iteration: 3
Solving Pairwise Slice Alignment Problem.
Solving Center Mapping NMF Problem.
/opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/site-packages/sklearn/decomposition/_nmf.py:1759: ConvergenceWarning:
Maximum number of iterations 200 reached. Increase it to improve convergence.
Objective 1.3915310177258615
Difference: 0.003430001949679351
Iteration: 4
Solving Pairwise Slice Alignment Problem.
Solving Center Mapping NMF Problem.
/opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/site-packages/sklearn/decomposition/_nmf.py:1759: ConvergenceWarning:
Maximum number of iterations 200 reached. Increase it to improve convergence.
Objective 1.3930793721374746
Difference: 0.001548354411613051
Iteration: 5
Solving Pairwise Slice Alignment Problem.
Solving Center Mapping NMF Problem.
/opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/site-packages/sklearn/decomposition/_nmf.py:1759: ConvergenceWarning:
Maximum number of iterations 200 reached. Increase it to improve convergence.
Objective 1.3952582931024906
Difference: 0.00217892096501604
Iteration: 6
Solving Pairwise Slice Alignment Problem.
Solving Center Mapping NMF Problem.
Objective 1.395387189225354
Difference: 0.0001288961228633756
Runtime: 24.881673574447632
/opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/site-packages/sklearn/decomposition/_nmf.py:1759: ConvergenceWarning:
Maximum number of iterations 200 reached. Increase it to improve convergence.
Again, we can run center align without providing intial mappings below.
[19]:
# center_slice, pis = paste.center_align(initial_slice, slices, lmbda, random_seed = 5)
center_slice returns an AnnData object that also includes the low dimensional representation of our inferred center slice.
[20]:
center_slice.uns["paste_W"]
[20]:
array([[2.56406096e-02, 1.17735607e+00, 1.45992052e-01, ...,
1.67005417e-02, 8.65816830e-03, 1.64249356e-02],
[1.93239963e-03, 3.38372964e-01, 1.80787142e-01, ...,
1.61882816e-02, 1.01921081e-03, 4.46527738e-02],
[4.19665780e-01, 1.88694808e-01, 2.90303299e-02, ...,
4.75023417e-02, 1.62389941e-02, 1.17923347e-01],
...,
[2.91596139e-02, 8.19205064e-03, 1.07181457e-01, ...,
4.61294228e-04, 4.20524970e-04, 2.33305743e-01],
[4.31159614e-02, 3.82986846e-02, 1.78688011e-01, ...,
9.82425931e-03, 3.23265909e-03, 2.58807000e-01],
[1.83314288e-01, 1.68948947e-05, 2.22536848e-02, ...,
1.16837125e-05, 4.58040720e-03, 9.97049976e-02]])
[21]:
center_slice.uns["paste_H"]
[21]:
array([[9.00595612e-01, 1.28095199e-01, 7.99820102e-02, ...,
5.45671916e-03, 4.42535703e-02, 2.77099832e-02],
[1.84556879e+00, 1.12907519e-01, 3.19053467e-01, ...,
1.01912360e-01, 1.03440812e-01, 3.08299141e-02],
[1.93982112e+00, 1.42403634e-01, 1.30713056e-01, ...,
7.35120042e-02, 3.50568628e-02, 2.86018512e-02],
...,
[3.05294214e+00, 1.88580787e-01, 3.20976584e-01, ...,
2.51081651e-02, 5.00735586e-06, 1.10129734e-02],
[9.20159439e-01, 1.65184158e-01, 1.04867309e-01, ...,
1.26153758e-02, 1.25054026e-02, 2.44712739e-02],
[5.73756511e+00, 7.43537949e-04, 3.13147993e-01, ...,
6.80617572e-06, 3.99149860e-02, 2.55630177e-13]])
Center slice alignment plots
Next, we can use the outputs of center_align to align the slices.
[22]:
center, new_slices = stack_slices_center(center_slice, slices, pis)
Now that we’ve aligned the spatial coordinates, we can plot them all on the same coordinate system. Note the center slice is not plotted.
[23]:
center_color = "orange"
slices_colors = ["#e41a1c", "#377eb8", "#4daf4a", "#984ea3"]
plt.figure(figsize=(7, 7))
plot_slice(center, center_color, s=400)
for i in range(len(new_slices)):
plot_slice(new_slices[i], slices_colors[i], s=400)
plt.legend(
handles=[
mpatches.Patch(color=slices_colors[0], label="1"),
mpatches.Patch(color=slices_colors[1], label="2"),
mpatches.Patch(color=slices_colors[2], label="3"),
mpatches.Patch(color=slices_colors[3], label="4"),
]
)
plt.gca().invert_yaxis()
plt.axis("off")
plt.show()
Next, we plot each slice compared to the center.
Note that since we used slice1 as the coordinates for the center slice, they remain the same, and thus we cannot see both in our plots below.
[24]:
center_color = "orange"
slice_colors = ["#e41a1c", "#377eb8", "#4daf4a", "#984ea3"]
fig, axs = plt.subplots(2, 2, figsize=(7, 7))
plot_slice(center, center_color, ax=axs[0, 0])
plot_slice(new_slices[0], slice_colors[0], ax=axs[0, 0])
plot_slice(center, center_color, ax=axs[0, 1])
plot_slice(new_slices[1], slice_colors[1], ax=axs[0, 1])
plot_slice(center, center_color, ax=axs[1, 0])
plot_slice(new_slices[2], slice_colors[2], ax=axs[1, 0])
plot_slice(center, center_color, ax=axs[1, 1])
plot_slice(new_slices[3], slice_colors[3], ax=axs[1, 1])
plt.show()
Gpu Implementation
POT allows us to write backend agnostic code, allowing us to use Numpy, Pytorch, etc to calculate our computations (https://pythonot.github.io/gen_modules/ot.backend.html).
We have updated our code to include gpu support for Pytorch.
First, you want to make sure you have torch installed. One way to check is by running:
[25]:
import ot
ot.backend.get_backend_list()
[25]:
[<ot.backend.NumpyBackend at 0x7fb286cd48f0>,
<ot.backend.TorchBackend at 0x7fb27e4ded50>]
By default, you should have ot.backend.NumpyBackend(). To use our gpu, make sure you have ot.backend.TorchBackend().
If not, install torch: https://pytorch.org/
Note: From our tests, ot.backend.TorchBackend() is still faster than ot.backend.NumpyBackend() even if you ONLY use cpu, so we recommend trying it if you would like to speed up your calculations.
Now, assuming you have torch installed, we check to make sure you have access to gpu. PASTE automatically does this check for you, but it is still helpful to know if you want to debug why you can’t seem to access your gpu.
[26]:
import torch
torch.cuda.is_available()
[26]:
False
Running PASTE with gpu
Note: Since the breast dataset is small, cpu may actually be faster than gpu in this particular case. For larger datasets, you will see a greater improvement in gpu vs cpu.
First, we read in our data.
[27]:
data_dir = "../../../tests/data/input/"
# Assume that the coordinates of slices are named slice_name + "_coor.csv"
def load_slices(data_dir, slice_names=["slice1", "slice2", "slice3", "slice4"]):
slices = []
for slice_name in slice_names:
slice_i = sc.read_csv(data_dir + slice_name + ".csv")
slice_i_coor = np.genfromtxt(data_dir + slice_name + "_coor.csv", delimiter=",")
slice_i.obsm["spatial"] = slice_i_coor
# Preprocess slices
sc.pp.filter_genes(slice_i, min_counts=15)
sc.pp.filter_cells(slice_i, min_counts=100)
slices.append(slice_i)
return slices
slices = load_slices(data_dir)
slice1, slice2, slice3, slice4 = slices
Next, running with gpu is as easy as setting two parameters in our function.
[28]:
start = time.time()
pi12 = pairwise_align(slice1, slice2, backend=ot.backend.TorchBackend(), use_gpu=False)
pi23 = pairwise_align(slice2, slice3, backend=ot.backend.TorchBackend(), use_gpu=False)
pi34 = pairwise_align(slice3, slice4, backend=ot.backend.TorchBackend(), use_gpu=False)
print("Runtime: " + str(time.time() - start))
Using selected backend cpu. If you want to use gpu, set use_gpu = True.
Using selected backend cpu. If you want to use gpu, set use_gpu = True.
/opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/site-packages/paste3/helper.py:27: UserWarning:
The use of `x.T` on tensors of dimension other than 2 to reverse their shape is deprecated and it will throw an error in a future release. Consider `x.mT` to transpose batches of matrices or `x.permute(*torch.arange(x.ndim - 1, -1, -1))` to reverse the dimensions of a tensor. (Triggered internally at ../aten/src/ATen/native/TensorShape.cpp:3683.)
Using selected backend cpu. If you want to use gpu, set use_gpu = True.
Runtime: 0.5100405216217041
[29]:
pd.DataFrame(pi12)
[29]:
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ... | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0.003937 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.000000e+00 | 0.000000 | 0.000000 |
| 1 | 0.000063 | 0.003874 | 0.000000 | 0.0 | 0.0 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.000000e+00 | 0.000000 | 0.000000 |
| 2 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.003937 | 0.000000 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.000000e+00 | 0.000000 | 0.000000 |
| 3 | 0.000000 | 0.000126 | 0.003811 | 0.0 | 0.0 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.000000e+00 | 0.000000 | 0.000000 |
| 4 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.000000 | 0.003874 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.000000e+00 | 0.000000 | 0.000000 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 249 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | 3.937008e-03 | 0.000000 | 0.000000 |
| 250 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | 6.299213e-05 | 0.003874 | 0.000000 |
| 251 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.000000 | 0.000126 | 0.003811 | 0.0 | 0.0 | 0.0 | 3.035766e-17 | 0.000000 | 0.000000 |
| 252 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.003748 | 0.000000 | 0.000189 | 0.0 | 0.0 | 0.0 | 0.000000e+00 | 0.000000 | 0.000000 |
| 253 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.0 | 0.0 | 0.000000e+00 | 0.000000 | 0.003937 |
254 rows × 250 columns
We do the same with center_align().
Note: This time, we skip providing initial mappings pi_init = b as previously done above.
[30]:
slices = load_slices(data_dir)
slice1, slice2, slice3, slice4 = slices
slices = [slice1, slice2, slice3, slice4]
initial_slice = slice1.copy()
lmbda = len(slices) * [1 / len(slices)]
[31]:
start = time.time()
center_slice, pis = center_align(
initial_slice,
slices,
lmbda,
random_seed=5,
backend=ot.backend.TorchBackend(),
use_gpu=False,
)
print("Runtime: " + str(time.time() - start))
Using selected backend cpu. If you want to use gpu, set use_gpu = True.
Filtered all slices for common genes. There are 6397 common genes.
/opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/site-packages/sklearn/decomposition/_nmf.py:1759: ConvergenceWarning:
Maximum number of iterations 200 reached. Increase it to improve convergence.
Iteration: 0
Solving Pairwise Slice Alignment Problem.
Solving Center Mapping NMF Problem.
/opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/site-packages/sklearn/decomposition/_nmf.py:1759: ConvergenceWarning:
Maximum number of iterations 200 reached. Increase it to improve convergence.
Objective -27.385402356804512
Difference: 27.385402356804512
Iteration: 1
Solving Pairwise Slice Alignment Problem.
Solving Center Mapping NMF Problem.
/opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/site-packages/sklearn/decomposition/_nmf.py:1759: ConvergenceWarning:
Maximum number of iterations 200 reached. Increase it to improve convergence.
Objective 1.3815814763824439
Difference: 28.766983833186956
Iteration: 2
Solving Pairwise Slice Alignment Problem.
Solving Center Mapping NMF Problem.
/opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/site-packages/sklearn/decomposition/_nmf.py:1759: ConvergenceWarning:
Maximum number of iterations 200 reached. Increase it to improve convergence.
Objective 1.3920834290254631
Difference: 0.01050195264301923
Iteration: 3
Solving Pairwise Slice Alignment Problem.
Solving Center Mapping NMF Problem.
/opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/site-packages/sklearn/decomposition/_nmf.py:1759: ConvergenceWarning:
Maximum number of iterations 200 reached. Increase it to improve convergence.
Objective 1.3945582891589245
Difference: 0.0024748601334614317
Iteration: 4
Solving Pairwise Slice Alignment Problem.
Solving Center Mapping NMF Problem.
/opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/site-packages/sklearn/decomposition/_nmf.py:1759: ConvergenceWarning:
Maximum number of iterations 200 reached. Increase it to improve convergence.
Objective 1.395587736891249
Difference: 0.0010294477323244955
Iteration: 5
Solving Pairwise Slice Alignment Problem.
Solving Center Mapping NMF Problem.
Objective 1.3956007949971019
Difference: 1.3058105852836732e-05
Runtime: 23.085625410079956
/opt/hostedtoolcache/Python/3.12.7/x64/lib/python3.12/site-packages/sklearn/decomposition/_nmf.py:1759: ConvergenceWarning:
Maximum number of iterations 200 reached. Increase it to improve convergence.